package com.wangping;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

import com.wangping.processors.ConsecutiveOccurrencesProcessor;
import com.wangping.processors.DiscardedProcessor;
import com.wangping.processors.EquivalentProcessor;
import com.wangping.processors.IProcessor;
import com.wangping.processors.IProcessor4List;
import com.wangping.processors.NonalphabeticProcessor;
import com.wangping.processors.WordCaseNotSensitiveProcessor;

public class Main {
	public final static String CONNECTOR_RESULTS = ", ";
	public final static String CONNECTOR_QA = ": ";
	private List<String> nameList = new ArrayList<String>();
	private List<String> nameList_backup = new ArrayList<String>();


	private List<IProcessor> Processors = new ArrayList<IProcessor>();
	private String username;
	private String username_backup;

	public static void main(String[] args) {
		Main main = new Main();
		main.doMain(args);
	}
	public String doMain(String[] args){
		String fileName = "";
		String userName = "";
		if(validateInputs(args)){
			userName = args[0];
			fileName = args[1];
		}else{
			dealWithInvalidInputs(args);
		}
		//load the file and put names into name list.
		initNameList(fileName);
		setUsername(userName);
		//backup
		setUsername_backup(userName);
		//Initialize all processors
		initProcessors();
		//process username, such as remove non alphabetic characters...
		userName = process(userName);
		setUsername(userName);
		//process all names, such as remove non alphabetic characters...
		process(getNameList());
		
		//System.out.println(main);
		//Phonetic Search
		return phoneticCheck();
	}
	private boolean validateInputs(String[] args){
		boolean returnVar = false;
		if(args.length == 2){
			if(args[0].trim().isEmpty()){
				returnVar = false;
			}else if(args[1].trim().isEmpty()){
				returnVar = false;
			}else{
				returnVar =  true;
			}
		}else{
			returnVar = false;
		}
		return returnVar;
	}
	private void dealWithInvalidInputs(String[] args){
		System.err.println("Error, please run this program like this:  >java com/wangping/Main <name> <xx/xx/surname.txt>");
		System.exit(0);
	}

	/*
	 * The matching algorithm is as follows:
		1. All non-alphabetic characters are ignored
		2. Word case is not significant
		3. After the first letter, any of the following letters are discarded: A, E, I, H, O, U, W, Y.
		4. The following sets of letters are considered equivalent
		  A,E,I,O,U
		  C,G,J,K,Q,S,X,Y,Z
		  B,F,P,V,W
		  D,T
		  M,N
		  All others have no equivalent
		5. Any consecutive occurrences of equivalent letters (after discarding letters in step 3) are considered as a single occurrence
		The rules should be applied in that order
	 */
	private void initProcessors(){
		//TODO all processors should be singleton. but it is fine for this application now.
		Processors.add(new NonalphabeticProcessor());//1
		Processors.add(new WordCaseNotSensitiveProcessor());//2
		Processors.add(new DiscardedProcessor());//3
		Processors.add(new EquivalentProcessor());//4
		Processors.add(new ConsecutiveOccurrencesProcessor());//5
	}
	
	private String process(String str){
		for (IProcessor processor : Processors) {
			str = processor.process(str);
		}
		return str;
	}
	
	private void process(List<String> list){
		for (IProcessor processor : Processors) {
			if(processor instanceof IProcessor4List){
				((IProcessor4List) processor).process(list);
			}
		}
	}
	
	/*
	 * the final Phonetic Search
	 */
	private String phoneticCheck(){
		List<String> names = this.getNameList();
		List<String> result = new ArrayList<String>();
		String resultString = "";
		
		for (int i = 0 ; i<names.size() ; i++) {
			String namea = names.get(i);
			String nameb = this.getUsername();
			if(namea.equals(nameb)){
				String temp = this.getNameList_backup().get(i);
				result.add(temp);
			}
		}
		
		//print out the result.
		StringBuffer sb = new StringBuffer(this.getUsername_backup());
		sb.append(CONNECTOR_QA);
		for (String string : result) {
			sb.append(string);
			sb.append(CONNECTOR_RESULTS);
		}
		String temp = sb.substring(sb.length()-2);
		if(temp.equals(CONNECTOR_RESULTS)){
			resultString = sb.substring(0, sb.length()-2);
		}else{
			resultString = sb.toString();
		}
		System.out.println(resultString);
		return resultString;
		
	}
	/*
	 * load names from the given file.
	 */
	private void initNameList(String fileName) {
		FileInputStream fstream = null;
		BufferedReader br = null;
		//clean all first
		if(nameList == null){
			nameList = new ArrayList<String>();
		}
		if(nameList_backup == null){
			nameList_backup = new ArrayList<String>();
		}
		nameList.clear();
		nameList_backup.clear();
		
		try {
			fstream = new FileInputStream(fileName);
			br = new BufferedReader(new InputStreamReader(fstream));
			String strLine;
			while ((strLine = br.readLine()) != null){
				//System.out.println (strLine);
				nameList.add(strLine);
				strLine = strLine.trim();// trim backup names. backup names are used for display.
				//backup
				nameList_backup.add(strLine);
			}
		} catch (FileNotFoundException e) {
			//e.printStackTrace();
			System.err.println("Error, the surname file does not exsit. ");
			System.exit(0);
		} catch (IOException e) {
			e.printStackTrace();
		}
		finally{
			if(br != null){
				try {
					br.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

	public List<String> getNameList() {
		return nameList;
	}

	public void setNameList(List<String> nameList) {
		this.nameList = nameList;
	}

	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}
	
	public List<String> getNameList_backup() {
		return nameList_backup;
	}

	public void setNameList_backup(List<String> nameList_backup) {
		this.nameList_backup = nameList_backup;
	}

	public String getUsername_backup() {
		return username_backup;
	}

	public void setUsername_backup(String username_backup) {
		this.username_backup = username_backup;
	}

	@Override
	public String toString() {
		return "Main [nameList=" + nameList + ", \nnameList_backup="
				+ nameList_backup + ", \nProcessors=" + Processors
				+ ", \nusername=" + username + ", \nusername_backup="
				+ username_backup + "]";
	}

	
}
